package com.zaimokuza.cn.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zaimokuza.cn.entity.PageResult;
import com.zaimokuza.cn.entity.auth.Resources;
import com.zaimokuza.cn.entity.auth.Role;
import com.zaimokuza.cn.entity.constants.FileConstant;
import com.zaimokuza.cn.entity.enums.CustomizeExceptionEnum;
import com.zaimokuza.cn.entity.user.*;
import com.zaimokuza.cn.mapper.UserMapper;
import com.zaimokuza.cn.mapper.UserSpreadMapper;
import com.zaimokuza.cn.service.MessageService;
import com.zaimokuza.cn.service.ResourcesService;
import com.zaimokuza.cn.service.RoleService;
import com.zaimokuza.cn.service.UserService;
import com.zaimokuza.cn.util.AssertUtils;
import com.zaimokuza.cn.util.RandomUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.zaimokuza.cn.entity.constants.UserConstant.ALERT_ADMIN_ID;

/**
 * @author zaimokuza
 */
@Service
public class UseServiceImpl implements UserService, UserDetailsService {

    @Resource
    private MessageService messageService;
    @Resource
    private ResourcesService resourcesService;
    @Resource
    private RoleService roleService;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserSpreadMapper userSpreadMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    /**
     * 校验用户信息
     *
     * @param detailedUser 用户信息
     */
    private void checkUser(DetailedUser detailedUser) {
        // 校验名称是否被使用
        Integer nameIsUse = userMapper.queryNameIsRepeat(detailedUser.getId(), detailedUser.getName());
        AssertUtils.isNull(nameIsUse, CustomizeExceptionEnum.USER_NAME_IS_REPEAT);
        // 校验手机号是否被使用
        Integer phoneIsUse = userMapper.queryPhoneIsRepeat(detailedUser.getId(), detailedUser.getPhone());
        AssertUtils.isNull(phoneIsUse, CustomizeExceptionEnum.USER_PHONE_IS_REPEAT);
    }

    @Override
    public void register(RegisterUser registerUser) {
        // 转换User对象
        DetailedUser detailedUser = new DetailedUser();
        BeanUtils.copyProperties(registerUser, detailedUser);
        // 生成ID
        detailedUser.setId(RandomUtils.get32Uid());
        // 设置默认头像
        detailedUser.setAvatar(FileConstant.DEFAULT_AVATAR);
        // 校验用户信息
        checkUser(detailedUser);
        // 对密码进行加密
        detailedUser.setPassword(passwordEncoder.encode(detailedUser.getPassword()));
        // 添加记录
        userMapper.insertUserRecord(detailedUser);
        userSpreadMapper.insertUserSpread(detailedUser.getId());
    }

    @Override
    public void saveLoginRecord(String userId) {
        userMapper.insertUserLoginRecord(userId);
    }

    @Override
    public void updateUser(DetailedUser detailedUser) {
        // 校验用户信息
        checkUser(detailedUser);
        // 校验域名是否被使用
        Integer domainIsRepeat = userMapper.queryDomainIsRepeat(detailedUser.getId(), detailedUser.getDomain());
        AssertUtils.isNull(domainIsRepeat, CustomizeExceptionEnum.USER_DOMAIN_IS_REPEAT);
        // 更新记录
        userMapper.updateUserRecord(detailedUser);
    }

    @Override
    public LoginUser getUserLoginInfo(String userId) {
        // 查询登录后的用户基础信息
        LoginUser loginUser = userMapper.queryLoginUser(userId);
        // 查询用户资源信息
        ArrayList<Resources> resourcesList = resourcesService.getResourcesListByUserId(userId);
        loginUser.setResourcesList(resourcesList);
        // 返回
        return loginUser;
    }

    @Override
    public BriefUser getBriefUser(BriefUser param, String userId) {
        // 查询用户检要信息
        BriefUser briefUser = userMapper.queryBriefUser(param, userId);
        // 校验用户是否存在
        AssertUtils.notNull(briefUser, CustomizeExceptionEnum.USER_NOT_FOUND);
        // 完善信息
        briefUser.setIsOwner(userId != null && userId.equals(briefUser.getId()));
        // 返回
        return briefUser;
    }

    @Override
    public DetailedUser getDetailedUser(String id) {
        return userMapper.queryDetailedUser(id);
    }

    @Override
    public ArrayList<BriefUser> getRecommendUserList(String userId) {
        // 查询推荐用户列表
        ArrayList<BriefUser> recommendUserList = userMapper.queryRecommendUserList(userId);
        // 遍历完善信息
        for (BriefUser briefUser : recommendUserList) {
            briefUser.setIsOwner(userId != null && userId.equals(briefUser.getId()));
        }
        return recommendUserList;
    }

    @Override
    public ArrayList<BriefUser> getSearchUserList(String name, String userId, String time) {
        // 查询推荐用户列表
        ArrayList<BriefUser> searchUserList = userMapper.querySearchUserList(name, userId, time);
        // 遍历完善信息
        for (BriefUser briefUser : searchUserList) {
            briefUser.setIsOwner(userId != null && userId.equals(briefUser.getId()));
        }
        return searchUserList;
    }

    @Override
    public PageResult<BriefUser> getFollowerPage(String domain, String userId, Integer page, Integer size) {
        // 设置分页信息
        PageHelper.startPage(page, size);
        // 查询
        Page<BriefUser> briefUserPage = userMapper.queryFollowerPage(domain, userId);
        // 遍历完善信息
        for (BriefUser briefUser : briefUserPage.getResult()) {
            briefUser.setIsOwner(userId != null && userId.equals(briefUser.getId()));
        }
        // 包装返回
        return PageResult.from(briefUserPage);
    }

    @Override
    public PageResult<BriefUser> getFollowingPage(String domain, String userId, Integer page, Integer size) {
        // 设置分页信息
        PageHelper.startPage(page, size);
        // 查询
        Page<BriefUser> briefUserPage = userMapper.queryFollowingPage(domain, userId);
        // 遍历完善信息
        for (BriefUser briefUser : briefUserPage.getResult()) {
            briefUser.setIsOwner(userId != null && userId.equals(briefUser.getId()));
        }
        // 包装返回
        return PageResult.from(briefUserPage);
    }

    @Override
    public PageResult<ContactUser> getContactUserPage(String userId, Integer page, Integer size) {
        // 分页
        PageHelper.startPage(page, size);
        // 查询
        Page<ContactUser> contactUserPage = userMapper.queryContactUserPage(userId);
        // 获取联系人列表
        List<ContactUser> contactInfos = contactUserPage.getResult();
        // 遍历联络人列表
        ArrayList<String> contactUserIdList = new ArrayList<>();
        for (ContactUser contactInfo : contactInfos) {
            // 整理联络人ID集合
            contactUserIdList.add(contactInfo.getId());
            // 对管理员信息进行特殊处理
            if (ALERT_ADMIN_ID.equals(contactInfo.getId())) {
                contactInfo.setName("@ Cetacea管理员 @");
                contactInfo.setAvatar("/image/avatar/default.jpg");
            }
        }
        // 完善联系人未读消息数量
        if (!CollectionUtils.isEmpty(contactUserIdList)) {
            // 查询联系人未读消息数量
            HashMap<String, Long> contactUserUnreadNumberMap = messageService.getContactUserUnreadNumber(userId, contactUserIdList);
            // 整理进结果集合
            for (ContactUser contactInfo : contactInfos) {
                contactInfo.setUnreadCount(contactUserUnreadNumberMap.getOrDefault(contactInfo.getId(), 0L));
            }
        }
        // 封装结果并返回
        return PageResult.from(contactUserPage);
    }

    @Override
    public PageResult<BriefUser> getBriefUserPage(String name, String userId, Integer page, Integer size) {
        // 设置分页信息
        PageHelper.startPage(page, size);
        // 整理查询条件
        BriefUser param = new BriefUser();
        param.setName(name);
        // 查询
        Page<BriefUser> briefUserPage = userMapper.queryBriefUserPage(param, userId);
        // 包装返回
        return PageResult.from(briefUserPage);
    }

    @Override
    public String getUserNameById(String id) {
        return userMapper.queryUserNameById(id);
    }

    @Override
    public ArrayList<String> getUserIdList() {
        return userMapper.queryUserIdList();
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 根据用户名查询用户信息
        SecurityUser securityUser = userMapper.querySecurityUserByPhone(username);
        // 如果没有查询到用户信息则该用户未注册
        if (securityUser == null) {
            throw new InternalAuthenticationServiceException("");
        }
        // 查询用户角色和资源信息
        ArrayList<Role> roleList = roleService.getRoleListByUserId(securityUser.getId());
        // 整理用户权限信息
        ArrayList<GrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roleList) {
            // 角色
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
        }
        securityUser.setAuthorities(authorities);
        // 返回用户
        return securityUser;
    }

    /* 统计相关操作 */

    @Override
    public void increaseBlogTotal(String userId) {
        userSpreadMapper.increaseBlogTotal(userId);
    }

    @Override
    public void reduceBlogTotal(String userId) {
        userSpreadMapper.reduceBlogTotal(userId);
    }

    @Override
    public void increaseFollowers(String userId) {
        userSpreadMapper.increaseFollowers(userId);
    }

    @Override
    public void reduceFollowers(String userId) {
        userSpreadMapper.reduceFollowers(userId);
    }

    @Override
    public void increaseFollowing(String userId) {
        userSpreadMapper.increaseFollowing(userId);
    }

    @Override
    public void reduceFollowing(String userId) {
        userSpreadMapper.reduceFollowing(userId);
    }

}
